﻿using UnityEngine;
using UnityEngine.UI;

public class DrawToObject : MonoBehaviour
{
    /// <summary>
    /// 绘制的目标图片
    /// </summary>
    public RenderTexture rt;
    /// <summary>
    /// 笔刷
    /// </summary>
    public Texture2D brushTexture;

    /// <summary>
    /// 空白图
    /// </summary>
    public Texture2D blankTexture;

    /// <summary>
    /// 模型
    /// </summary>
    public Transform modelTransform;

    /// <summary>
    /// 笔刷大小滑条
    /// </summary>
    public Slider brushSizeSlider;

    /// <summary>
    /// 主摄像机
    /// </summary>
    private Camera mainCam;

    private const int orrBrushSize = 50;

    // Start is called before the first frame update
    void Start()
    {
        mainCam = Camera.main;
        DrawBlank();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                // hit.textureCoord是碰撞点的uv值，uv值是从0到1的，所以要乘以宽高才能得到具体坐标点
                var x = (int)(hit.textureCoord.x * rt.width);
                // 注意，uv坐标系和Graphics坐标系的y轴方向相反
                var y = (int)(rt.height - hit.textureCoord.y * rt.height);
                Draw(x, y);
            }
        }

        // 按左右方向键，旋转模型
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            modelTransform.Rotate(0, 360 * Time.deltaTime, 0);
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            modelTransform.Rotate(0, -360 * Time.deltaTime, 0);
        }
    }

    /// <summary>
    /// 初始化RenderTexture
    /// </summary>
    private void DrawBlank()
    {
        // 激活rt
        RenderTexture.active = rt;
        // 保存当前状态
        GL.PushMatrix();
        // 设置矩阵
        GL.LoadPixelMatrix(0, rt.width, rt.height, 0);

        //for (int i = 0; i < blankTexture.width; i++)
        //{
        //    for (int j = 0; j < blankTexture.height; j++)
        //    {
        //        blankTexture.SetPixel(i, j, Color.black);
        //    }
        //}
        //blankTexture.Apply();
        // 绘制贴图
        Rect rect = new Rect(0, 0, rt.width, rt.height);
        Graphics.DrawTexture(rect, blankTexture);

        // 弹出改变
        GL.PopMatrix();

        RenderTexture.active = null;
    }

    /// <summary>
    /// 在RenderTexture的(x,y)坐标处画笔刷图案
    /// </summary>
    private void Draw(int x, int y)
    {
        // 激活rt
        RenderTexture.active = rt;
        // 保存当前状态
        GL.PushMatrix();
        // 设置矩阵
        GL.LoadPixelMatrix(0, rt.width, rt.height, 0);

        for (int i = 0; i < brushTexture.width; i++)
        {
            for (int j = 0; j < brushTexture.height; j++)
            {
                if (brushTexture.GetPixel(i, j).a != 0)
                    brushTexture.SetPixel(i, j, ColorPicker.pickColor);
            }
        }

        int tmpWidth = (int)(orrBrushSize * brushSizeSlider.value);
        int tmpHeight = (int)(orrBrushSize * brushSizeSlider.value);

        tmpWidth = tmpWidth < orrBrushSize ? orrBrushSize : tmpWidth;
        tmpHeight = tmpHeight < orrBrushSize ? orrBrushSize : tmpHeight;

        //brushTexture.Resize(tmpWidth, tmpHeight);
        brushTexture = ScaleTexture(brushTexture, tmpWidth, tmpHeight);
        brushTexture.Apply();

        // 绘制贴图
        x -= (int)(tmpWidth * 0.5);
        y -= (int)(tmpHeight * 0.5);
        Rect rect = new Rect(x, y, tmpWidth, tmpHeight);

        Graphics.DrawTexture(rect, brushTexture);

        // 弹出改变
        GL.PopMatrix();

        RenderTexture.active = null;
    }

    Texture2D ScaleTexture(Texture2D source, float targetWidth, float targetHeight)
    {
        Texture2D result = new Texture2D((int)targetWidth, (int)targetHeight, source.format, false);

        for (int i = 0; i < result.height; ++i)
        {
            for (int j = 0; j < result.width; ++j)
            {
                Color newColor = source.GetPixelBilinear((float)j / result.width, (float)i / result.height);
                result.SetPixel(j, i, newColor);
            }
        }

        result.Apply();
        return result;
    }
}
